<?php
/**
 * 描述：网站会员实体类。
 * @final
 */
final class Account
{   
    const COOKIENAME_USERNAME='__shipinall_wy_zrx_dht_zy_2012__a0po&&%#$________lI*^*d%(&*km$&^*&nvb_username';
    const COOKIENAME_PASSWORD='__shipinall_wy_zrx_dht_zy_2012__a0po&&%#$________lI*^*d%(&*km$&^*&nvb_password';
    const SESSIONNAME_LOGINERRORCOUNT='__shipinall_wy_zrx_dht_zy_2012__a0po_session_loginerrorcount';
    const SESSIONNAME_LOGINCAPTCHA='__shipinall_wy_zrx_dht_zy_2012__a0po_session_logincaptcha';
    const SESSIONNAME_REGISTER_CAPTCHA='__shipinall_wy_zrx_dht_zy_2012__a0po_session_register_captcha';
    const SESSIONNAME_REGISTERDATA='__shipinall_wy_zrx_dht_zy_2012__a0po_session_registerdata';
    const SESSIONNAME_REGISTER_RESNEDCAPTCHA='__shipinall_wy_zrx_dht_zy_2012__a0po_session_register_resendcaptcha';
    const SESSIONNAME_FINDPASSWORD='__shipinall_wy_zrx_dht_zy_2012__a0po_session_findpassword';
    const SESSIONNAME_FINDPASSWORD_FIRST='__shipinall_wy_zrx_dht_zy_2012__a0po_session_findpassword_first';
    const SESSIONNAME_FINDPASSWORD_SECOND='__shipinall_wy_zrx_dht_zy_2012__a0po_session_findpassword_second';
    const SESSIONNAME_FINDPASSWORD_FIRST_CAPTCHA='__shipinall_wy_zrx_dht_zy_2012__a0po_session_findpassword_first_capcha';    
    private static $PublicKey='_#$__A1sd&645C5^*^B8EO*&**74A6F4D8Z10P;/.LODFM(*&((9^((NC86NV';

    private $Username=NULL;                 
    private $Password=NULL;
    private $Data=NULL;
    private $IsPasswordEncryption=NULL;  
    private $VerifyStatus=NULL;

    public function __Construct($username,$password=NULL,$isPasswordEncryption=FALSE)
    {
        #设置用户名
        $this->Username=$username;
        $this->Password=$password;
        $this->IsPasswordEncryption=$isPasswordEncryption;

        #设计密码
        if($this->Password&&($this->IsPasswordEncryption==FALSE)){
            $this->Password=self::EncryptPassword($this->Password,$this->Username);
        }

        #获取数据
        //参数值
        $sql='select * from account where Username=? and Username not in (select Account from account_delete)';
        $paramsValue=array($this->Username);
        $data=DB::PGetRows($sql,$paramsValue);
        if($data){
            $this->Data=$data[0];
        }
    }

    /**
     * 描述：获取私有属性
     */
    public function __Get($name)
    {
        switch($name)
        {
            case 'Username':
                return $this->Username;
            break;
            case 'Password':
                return $this->Password;
            break;
            case 'Data':
                return $this->Data;
            break;
            default :
                return NULL;
        }
    }

    /**
     * 描述：核实会员可用性
     */
    public function Verify()
    {

        #是否存在
        if(!$this->IsExists()){
            return $this->VerifyStatus='Inexistence';
        }

        #是否通过邮件验证
        if(!$this->IsEmailCheck()){
            return $this->VerifyStatus='EmailUnverified';
        }

        #是否锁定
        if($this->IsLocked()){
            return $this->VerifyStatus='Locked';
        }

        #是否密码正确
        if(!$this->IsPassword()){
            return $this->VerifyStatus='PasswordWrong';
        }

        return $this->VerifyStatus='Normal';
    }

    /**
     * 描述：更新数据。
     */
    public function Update($data)
    {
        #更新数据表信息
        $result=DB::UpdateRowByField('account','Username:'.$this->Username,$data);

        #更新对象信息
        if($result)
        {
            if(array_key_exists('Password',$data))
            {
                $this->Password=$data['Password'];
            }
            foreach($data as $key=>$value)
            {
                if($this->Data[$key])
                {
                    $this->Data[$key]=$value;
                }
            }
        }       
    }   

    /**
     * 描述：检测会员是不是存在。
     */
    public function IsExists()
    {
        #返回结果
        if($this->Data){
            return TRUE;
        }
        else{
            return FALSE;
        }
    }

    /**
     * 描述：检测密码是不是正确。
     */
    public function IsPassword()
    {       
        if($this->Data)
        {
            if($this->Data['Password']==$this->Password){
                return TRUE;
            }
            else{
                return FALSE;
            }
        }
        else{
            return FALSE;
        }
    }

    /**
     * 描述：邮件是否通过验证
     */
    public function IsEmailCheck()
    {
        #获取数据
        $data=DB::PGetRows('select ID from account_email_verification where Account=? limit 0,1',array
        (
            $this->Username
        ));
        
        #逻辑
        if($data){
            return TRUE;
        }
        else{
            return FALSE;
        }
    }

    /**
     * 描述：用户状态是否被锁定
     */
    public function IsLocked()
    {
        #获取数据
        $data=DB::PGetRows('select ID from account_locked where Account=? limit 0,1',array
        (
            $this->Username
        ));
        
        if($data)
        {            
            return TRUE;
        }
        else{
            return FALSE;
        }
    }

    /**
     * 描述：是否己经登录
     */
    public function IsLogin()
    {        
        if(Account::Session('Username')&&Account::Session('Password'))
        {
            return TRUE;
        }
        return FALSE;
    }

    /**
     * 执行登录会员时作的操作
     */
    public function Login()
    {
        #用户名cookie写入
        Cookie::Set(self::COOKIENAME_USERNAME,$this->Username,NULL,'/','.shipinall.cn');

        #密码cookie写入
        Cookie::Set(self::COOKIENAME_PASSWORD,$this->Password,NULL,'/','.shipinall.cn');

        #更新数据库
        DB::PExec('update account set Login_Datetime=?,Login_Count=Login_Count+1 where Username=?',array
        (
            date('Y-m-d G:i:s'),
            $this->Username
        ));

        #清除未成功登录时记录的次数
        Session::Set(self::SESSIONNAME_LOGINERRORCOUNT,NULL);
    }

    /**
     * 描述：记录登录错误。
     */
    public function Misregistration()
    {
        if(Session::Get(self::SESSIONNAME_LOGINERRORCOUNT))
        {
            Session::Set(self::SESSIONNAME_LOGINERRORCOUNT,Session::Get(self::SESSIONNAME_LOGINERRORCOUNT)+1);
        }
        else{
            Session::Set(self::SESSIONNAME_LOGINERRORCOUNT,1);
        }
    }

    /**
     * 会话注销
     */
    public function Logout()
    {
        #用户名
        Cookie::Delete(self::COOKIENAME_USERNAME,'/','.shipinall.cn');
        #密码
        Cookie::Delete(self::COOKIENAME_PASSWORD,'/','.shipinall.cn');
    }

    /**
     * 获取会话中的变量
     */
    public static function Session($name)
    {
        switch($name)
        {
            case 'Username':
                return Cookie::Get(self::COOKIENAME_USERNAME);
            break;
            case 'Password':
                return Cookie::Get(self::COOKIENAME_PASSWORD);
            break;
            default :
                return NULL;
        }
    }

    /**
     * 清除account会话
     */
    public static function Session_End()
    {
        Cookie::Set(self::COOKIENAME_USERNAME,NULL,NULL,'/','.shipinall.cn');
        Cookie::Set(self::COOKIENAME_PASSWORD,NULL,NULL,'/','.shipinall.cn');
    }

    /**
     * 检测是否需要进行验证码验证
     */
    public static function IsNeedCaptcha()
    {
        //当错误超过3次就需要验证码，返回真
        if(self::GetLoginErrorCount()>=3){
            return TRUE;
        }
        else{
            return FALSE;
        }
    }

    /**
     * 获取登录错误的次数
     */
    public static function GetLoginErrorCount()
    {                
        $loginErrorCount=Session::Get(self::SESSIONNAME_LOGINERRORCOUNT);
        return $loginErrorCount==NULL ? 0:$loginErrorCount;
    }

    /**
     * 加密密码的算法
     */
    public static function EncryptPassword($password,$factor)
    {
        $factor_a=bin2hex($factor[0]);
        $factor_b=bin2hex($factor[intval(strlen($factor)/2)]);
        $factor_c=bin2hex($factor[strlen($factor)-1]);        
        $password=md5($factor_a.'__'.$password.'__'.$factor_b.'__'.self::$PublicKey.'__'.$factor_c);
        return $password;
    }

    /**
     * 描述：获取随机会员随机码。
     */
    public static function RandomCode($header=NULL)
    {
        $charid=strtoupper(md5(uniqid(mt_rand(),true)));
        $hyphen=chr(45);// "-"
        $uuid=substr($charid, 0, 8).$hyphen
        .substr($charid, 8, 4).$hyphen
        .substr($charid,12, 4).$hyphen
        .substr($charid,16, 4).$hyphen
        .substr($charid,20,12);
        if($header){
            $uuid=$header.'-'.$uuid;
        }
        return 'Account-'.$uuid;
    }
}
?>